/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-07-26 16:27:42
 * @LastEditTime: 2021-08-04 11:44:20
 * @Description:  This files is for low-level ctrl of i2c functions
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 * 1.0   Zhugengyu   2021/8/3   init
 */
#ifndef BSP_DRIVERS_DW_I2C_HW_H
#define BSP_DRIVERS_DW_I2C_HW_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "kernel.h"
#include "ft_types.h"
#include "ft_io.h"
#include "dw_i2c.h"

/* Register Definition */
#define I2C_CON_OFFSET 0x00
#define I2C_TAR_OFFSET 0x04
#define I2C_SAR_OFFSET 0x08
#define I2C_HS_MADDR_OFFSET 0x0C
#define I2C_DATA_CMD_OFFSET 0x10
#define I2C_SS_SCL_HCNT_OFFSET 0x14
#define I2C_SS_SCL_LCNT_OFFSET 0x18
#define I2C_FS_SCL_HCNT_OFFSET 0x1C
#define I2C_FS_SCL_LCNT_OFFSET 0x20
#define I2C_HS_SCL_HCNT_OFFSET 0x24
#define I2C_HS_SCL_LCNT_OFFSET 0x28
#define I2C_INTR_STAT_OFFSET 0x2C
#define I2C_INTR_MASK_OFFSET 0x30
#define I2C_RAW_INTR_STAT_OFFSET 0x34
#define I2C_RX_TL_OFFSET 0x38
#define I2C_TX_TL_OFFSET 0x3C
#define I2C_CLR_INTR_OFFSET 0x40
#define I2C_CLR_RX_UNDER_OFFSET 0x44
#define I2C_CLR_RX_OVER_OFFSET 0x48
#define I2C_CLR_TX_OVER_OFFSET 0x4C
#define I2C_CLR_RD_REQ_OFFSET 0x50
#define I2C_CLR_TX_ABRT_OFFSET 0x54
#define I2C_CLR_RX_DONE_OFFSET 0x58
#define I2C_CLR_ACTIVITY_OFFSET 0x5c
#define I2C_CLR_STOP_DET_OFFSET 0x60
#define I2C_CLR_START_DET_OFFSET 0x64
#define I2C_CLR_GEN_CALL_OFFSET 0x68
#define I2C_ENABLE_OFFSET 0x6C
#define I2C_STATUS_OFFSET 0x70
#define I2C_TXFLR_OFFSET 0x74
#define I2C_RXFLR_OFFSET 0x78
#define I2C_SDA_HOLD_OFFSET 0x7c
#define I2C_TX_ABRT_SOURCE_OFFSET 0x80
#define I2C_SLV_DATA_NACK_ONLY_OFFSET 0x84
#define I2C_DMA_CR_OFFSET 0x88
#define I2C_DMA_TDLR_OFFSET 0x8c
#define I2C_DMA_RDLR_OFFSET 0x90
#define I2C_SDA_SETUP_OFFSET 0x94
#define I2C_ACK_GENERAL_CALL_OFFSET 0x98
#define I2C_ENABLE_STATUS_OFFSET 0x9C
#define I2C_FS_SPKLEN_OFFSET 0xa0
#define I2C_HS_SPKLEN_OFFSET 0xa4
#define I2C_COMP_PARAM_1_OFFSET 0xf4
#define I2C_COMP_VERSION_OFFSET 0xf8
#define I2C_COMP_TYPE_OFFSET 0xfc

//IC_CON
#define I2C_CON_MASTER_MODE      (0x1 << 0)
#define I2C_CON_SLAVE_MODE       (0x0 << 0)

#define I2C_CON_SPEED_MASK        GENMASK(2, 1)
#define I2C_CON_STD_SPEED        (0x1 << 1)
#define I2C_CON_FAST_SPEED       (0x2 << 1)
#define I2C_CON_HIGH_SPEED       (0x3 << 1)

/* for slave mode */
#define I2C_CON_SLAVE_ADR_7BIT  (0x0 << 3)
#define I2C_CON_SLAVE_ADR_10BIT (0x1 << 3)

/* for master mode */
#define I2C_CON_MASTER_ADR_7BIT  (0x0 << 4)
#define I2C_CON_MASTER_ADR_10BIT (0x1 << 4)

#define I2C_CON_RESTART_EN       (0x1 << 5)
#define I2C_CON_SLAVE_DISABLE    (0x1 << 6)

//IC_TAR
#define I2C_IC_TAR_MASK         GENMASK(9, 0)
#define I2C_GC_OR_START         (0x1 << 10)
#define I2C_SPECIAL             (0x1 << 11)
#define I2C_TAR_ADR_7BIT        (0x0 << 12)
#define I2C_TAR_ADR_10BIT       (0x1 << 12)

//IC_SAR
#define I2C_IC_SAR_MASK         GENMASK(9, 0) //Slave addr when in slave mode

//IC_HS_MADDR
#define I2C_IC_HS_MAR           GENMASK(2, 0) //I2C High Speed模式主机编码

//IC_DATA_CMD
#define I2C_DATA_MASK           GENMASK(7, 0)
#define I2C_DATA_CMD_READ       (0x1 << 8)
#define I2C_DATA_CMD_WRITE      (0x0 << 8)
#define I2C_DATA_CMD_STOP       (0x1 << 9)
#define I2C_DATA_CMD_RESTART    (0x1 << 10)

//IC_INTR_MASK & IC_INTR_STAT & IC_RAW_INTR_STAT
#define I2C_INTR_RX_UNDER (0x1 << 0)
#define I2C_INTR_RX_OVER (0x1 << 1)
#define I2C_INTR_RX_FULL (0x1 << 2)
#define I2C_INTR_TX_OVER (0x1 << 3)
#define I2C_INTR_TX_EMPTY (0x1 << 4)
#define I2C_INTR_RD_REQ (0x1 << 5)
#define I2C_INTR_TX_ABRT (0x1 << 6)
#define I2C_INTR_RX_DONE (0x1 << 7)
#define I2C_INTR_ACTIVITY (0x1 << 8)
#define I2C_INTR_STOP_DET (0x1 << 9)
#define I2C_INTR_START_DET (0x1 << 10)
#define I2C_INTR_GEN_CALL (0x1 << 11)

#define I2C_INTR_ALL_MASK           0x8FF
#define I2C_INTR_MASTER_DEF_MASK    (I2C_INTR_RX_FULL | I2C_INTR_TX_ABRT |\
                                     I2C_INTR_STOP_DET)
#define I2C_INTR_SLAVE_DEF_MASK     (I2C_INTR_RX_FULL | I2C_INTR_STOP_DET | \
                                     I2C_INTR_RD_REQ  | I2C_INTR_RX_DONE  | \
                                     I2C_INTR_RX_UNDER | I2C_INTR_TX_ABRT | \
                                     I2C_INTR_START_DET )

//IC_RX_TL
#define I2C_RX_TL_MASK     GENMASK(7, 0)

//IC_TX_TL
#define I2C_TX_TL_MASK     GENMASK(7, 0)

//IC_ENABLE
#define I2C_ENABLE_CONTROLLER 0x01
#define I2C_DISABLE_CONTROLLER 0x00

//IC_STATUS
#define I2C_STATUS_ACTIVITY             BIT(0)
#define I2C_STATUS_TFNF                 BIT(1)
#define I2C_STATUS_TFE                  BIT(2)
#define I2C_STATUS_RFNE                 BIT(3)
#define I2C_STATUS_RFF                  BIT(4)
#define I2C_STATUS_MST_ACTIVITY         BIT(5)
#define I2C_STATUS_SLV_ACTIVITY         BIT(6)

//IC_ENABLE_STATUS
#define I2C_IC_ENABLE                   (0x1 << 0)
#define I2C_IC_DISABLE                  (0x0 << 0)
#define I2C_IC_ENABLE_MASK              (0x1 << 0)

#define I2C_SLV_DISABLED_WHILE_BUSY     (0x1 << 1)
#define I2C_SLV_RX_DATA_LOST            (0x1 << 2)

/* High and low times in different speed modes (in ns) */
#define I2C_MIN_SS_SCL_HIGHTIME	4000
#define I2C_MIN_SS_SCL_LOWTIME	4700
#define I2C_MIN_FS_SCL_HIGHTIME	600
#define I2C_MIN_FS_SCL_LOWTIME	1300
#define I2C_MIN_FP_SCL_HIGHTIME	500
#define I2C_MIN_FP_SCL_LOWTIME	500
#define I2C_MIN_HS_SCL_HIGHTIME	60
#define I2C_MIN_HS_SCL_LOWTIME	160
#define I2C_DEFAULT_SDA_HOLD_TIME 300

/* I2C Register Operations */
#define I2C_BASE_ADDR(pCtrl) ((pCtrl)->config.baseAddr)
/**
 * @name: I2C_READ_REG32
 * @msg:  读取I2C寄存器
 * @param {u32} addr 定时器的基地址
 * @param {u32} reg_offset   定时器的寄存器的偏移
 * @return {u32} 寄存器参数
 */
#define I2C_READ_REG32(pCtrl, reg_offset) FtIn32(I2C_BASE_ADDR(pCtrl) + (u32)(reg_offset))

/**
 * @name: I2C_WRITE_REG32
 * @msg:  写入I2C寄存器
 * @param {u32} addr 定时器的基地址
 * @param {u32} reg_offset   定时器的寄存器的偏移
 * @param {u32} reg_value    写入寄存器参数
 * @return {void}
 */
#define I2C_WRITE_REG32(pCtrl, reg_offset, reg_value) FtOut32(I2C_BASE_ADDR(pCtrl) + (u32)(reg_offset), (u32)(reg_value))

#define I2C_ENABLE(pCtrl, regVal) I2C_WRITE_REG32(pCtrl, I2C_ENABLE_OFFSET, (regVal))
#define I2C_ENABLE_STAT(pCtrl)  I2C_READ_REG32(pCtrl, I2C_ENABLE_STATUS_OFFSET)
#define I2C_STATUS(pCtrl)  I2C_READ_REG32(pCtrl, I2C_STATUS_OFFSET)
#define I2C_WRITE_CON(pCtrl, regVal) I2C_WRITE_REG32(pCtrl, I2C_CON_OFFSET, (regVal))
#define I2C_READ_CON(pCtrl) I2C_READ_REG32(pCtrl, I2C_CON_OFFSET)
#define I2C_WRITE_RX_TL(pCtrl, regVal) I2C_WRITE_REG32(pCtrl, I2C_RX_TL_OFFSET, (regVal))
#define I2C_WRITE_TX_TL(pCtrl, regVal) I2C_WRITE_REG32(pCtrl, I2C_TX_TL_OFFSET, (regVal))
#define I2C_WRITE_INTR_MASK(pCtrl, regVal) I2C_WRITE_REG32(pCtrl, I2C_INTR_MASK_OFFSET, (regVal))
#define I2C_READ_INTR_MASK(pCtrl) I2C_READ_REG32(pCtrl, I2C_INTR_MASK_OFFSET)
#define I2C_READ_FS_SPKEN(pCtrl) I2C_READ_REG32(pCtrl, I2C_FS_SPKLEN_OFFSET)
#define I2C_READ_HS_SPKEN(pCtrl) I2C_READ_REG32(pCtrl, I2C_HS_SPKLEN_OFFSET)
#define I2C_WRITE_TAR(pCtrl, regVal)  I2C_WRITE_REG32(pCtrl, I2C_TAR_OFFSET, (regVal))
#define I2C_WRITE_SAR(pCtrl, regVal)  I2C_WRITE_REG32(pCtrl, I2C_SAR_OFFSET, (regVal))
#define I2C_WRITE_DATCMD(pCtrl, regVal) I2C_WRITE_REG32(pCtrl, I2C_DATA_CMD_OFFSET, (regVal))
#define I2C_READ_DATCMD(pCtrl) I2C_READ_REG32(pCtrl, I2C_DATA_CMD_OFFSET)
#define I2C_READ_RAW_INTR_STAT(pCtrl) I2C_READ_REG32(pCtrl, I2C_RAW_INTR_STAT_OFFSET)
#define I2C_READ_INTR_STAT(pCtrl)  I2C_READ_REG32(pCtrl, I2C_INTR_STAT_OFFSET)
#define I2C_CLEAR_ALL_IRQ(pCtrl) I2C_READ_REG32(pCtrl, I2C_CLR_INTR_OFFSET)

u32 I2cEnable(I2cCtrl *pCtrl, boolean enable);

#ifdef __cplusplus
}
#endif

#endif